package com.gxjtkyy.datadistributer.writer.rdbms.service;

import com.google.common.collect.Maps;
import com.gxjtkyy.datadistributer.common.exception.SettingException;
import com.gxjtkyy.datadistributer.writer.rdbms.config.TableSetting;
import com.gxjtkyy.datadistributer.writer.rdbms.config.WriterConfig;
import com.gxjtkyy.datadistributer.writer.rdbms.vo.DbTableSetting;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class DbWriterConfigService {
   private final WriterConfig writerConfig;

   @Cacheable(
      cacheNames = {"tableMetadata"},
      key = "#root.method+'_'+#root.args[0]"
   )
   public DbTableSetting getDbTableSetting(String originalTableName) {
      //源表名是否区分大小写
      Optional<TableSetting> tableSettingOptional = this.getTableSetting(originalTableName);
      if (!tableSettingOptional.isPresent()) {
         throw new SettingException("找不到分发表配置：originalTableName=" + originalTableName);
      } else {
         TableSetting tableSetting = (TableSetting)tableSettingOptional.get();
         String targetTableName = tableSetting.getTargetTableName();
         if (targetTableName == null) {
            targetTableName = originalTableName;
         }

         boolean updatable = tableSetting.isUpdatable();
         boolean columnCaseSensitive = this.writerConfig.isColumnCaseSensitive();
         //主键字段
         Set<String> keyColumns = (Set)tableSetting.getKeyColumns().stream().map((columnName) -> {
            return columnCaseSensitive ? columnName : columnName.toUpperCase();
         }).collect(Collectors.toSet());
         if (keyColumns.isEmpty()) {
            throw new SettingException("分发表配置缺少 keyColumns：originalTableName=" + originalTableName);
         } else {
            Set<String> ignoredColumnsForUpdate = (Set)tableSetting.getIgnoredColumnsForUpdate().stream().map((columnName) -> {
               return columnCaseSensitive ? columnName : columnName.toUpperCase();
            }).collect(Collectors.toSet());
            Set<String> ignoredColumnsForInsert = (Set)tableSetting.getIgnoredColumnsForInsert().stream().map((columnName) -> {
               return columnCaseSensitive ? columnName : columnName.toUpperCase();
            }).collect(Collectors.toSet());
//            Map<String, String> columnDefaultValues = tableSetting.getColumnDefaultValues().entrySet().stream().map((entry) -> {
//               String column = (String)entry.getKey();
//               if (!columnCaseSensitive) {
//                  column = column.toUpperCase();
//               }
//               return Map.entry(column, (String)entry.getValue());
//            }).collect(Collectors.toMap(Entry::getKey, Entry::getValue));
            //20241017报错修改
            Map<String, String> columnDefaultValues = tableSetting.getColumnDefaultValues().entrySet().stream()
                    .collect(Collectors.toMap(
                    entry -> {
                       String column = entry.getKey();
                       if (!columnCaseSensitive) {
                           column = column.toUpperCase();
                       }
                       return column;
                    },
                    Map.Entry::getValue,
                    (existing, replacement) -> existing,
                    HashMap::new));

            Map<String, String> comparableColumns = new HashMap(2);
            Iterator var12 = tableSetting.getComparableColumns().entrySet().iterator();

            while(var12.hasNext()) {
               Entry<String, String> comparableColumn = (Entry)var12.next();
               String key = ((String)comparableColumn.getKey()).toUpperCase();
               String value = (String)comparableColumn.getValue();
               comparableColumns.put(key, value);
            }

            DbTableSetting dbTableSetting = new DbTableSetting();
            dbTableSetting.setTargetTableName(targetTableName);
            dbTableSetting.setUpdatable(updatable);
            dbTableSetting.setColumnCaseSensitive(columnCaseSensitive);
            dbTableSetting.setKeyColumns(keyColumns);
            dbTableSetting.setComparableColumns(comparableColumns);
            dbTableSetting.setIgnoredColumnsForUpdate(ignoredColumnsForUpdate);
            dbTableSetting.setIgnoredColumnsForInsert(ignoredColumnsForInsert);
            dbTableSetting.setColumnDefaultValues(columnDefaultValues);
            dbTableSetting.setDbRecordFilterConfigs(tableSetting.getDbRecordFilterConfigs());
            dbTableSetting.setDropWhenCannotInsertNull(tableSetting.isDropWhenCannotInsertNull());
            dbTableSetting.setDropWhenValueTooLarge(tableSetting.isDropWhenValueTooLarge());
            dbTableSetting.setDropWhenValueLargeThanSpecifiedPrecision(tableSetting.isDropWhenValueLargeThanSpecifiedPrecision());
            return dbTableSetting;
         }
      }
   }

   /**源表名是否区分大小*/
   private Optional<TableSetting> getTableSetting(String originalTableName) {
      if (StringUtils.isBlank(originalTableName)) {
         return Optional.empty();
      } else {
         boolean tableCaseSensitive = this.writerConfig.isTableCaseSensitive();
         return this.writerConfig.getTableSettings().stream().filter((tableSetting) -> {
            return StringUtils.isNotBlank(tableSetting.getSourceTableName());
         }).filter((tableSetting) -> {
            String sourceTableName = tableSetting.getSourceTableName();
            return tableCaseSensitive ? sourceTableName.equals(originalTableName) : sourceTableName.equalsIgnoreCase(originalTableName);
         }).findFirst();
      }
   }

   public DbWriterConfigService(final WriterConfig writerConfig) {
      this.writerConfig = writerConfig;
   }
}
